[rand.dist.samp.discrete] git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@104103 91177308-0d34-0410-b5e6-96231b3b80d8 
diff --git a/include/random b/include/random index 6a3dcce..0ee6633 100644 --- a/include/random +++ b/include/random 
@@ -1410,7 +1410,71 @@  };    template<class IntType = int> - class discrete_distribution; +class discrete_distribution +{ +public: + // types + typedef IntType result_type; + + class param_type + { + public: + typedef discrete_distribution distribution_type; + + param_type(); + template<class InputIterator> + param_type(InputIterator firstW, InputIterator lastW); + param_type(initializer_list<double> wl); + template<class UnaryOperation> + param_type(size_t nw, double xmin, double xmax, UnaryOperation fw); + + vector<double> probabilities() const; + + friend bool operator==(const param_type& x, const param_type& y); + friend bool operator!=(const param_type& x, const param_type& y); + }; + + // constructor and reset functions + discrete_distribution(); + template<class InputIterator> + discrete_distribution(InputIterator firstW, InputIterator lastW); + discrete_distribution(initializer_list<double> wl); + template<class UnaryOperation> + discrete_distribution(size_t nw, double xmin, double xmax, + UnaryOperation fw); + explicit discrete_distribution(const param_type& parm); + void reset(); + + // generating functions + template<class URNG> result_type operator()(URNG& g); + template<class URNG> result_type operator()(URNG& g, const param_type& parm); + + // property functions + vector<double> probabilities() const; + + param_type param() const; + void param(const param_type& parm); + + result_type min() const; + result_type max() const; + + friend bool operator==(const discrete_distribution& x, + const discrete_distribution& y); + friend bool operator!=(const discrete_distribution& x, + const discrete_distribution& y); + + template <class charT, class traits> + friend + basic_ostream<charT, traits>& + operator<<(basic_ostream<charT, traits>& os, + const discrete_distribution& x); +  + template <class charT, class traits> + friend + basic_istream<charT, traits>& + operator>>(basic_istream<charT, traits>& is, + discrete_distribution& x); +};    template<class RealType = double>  class piecewise_constant_distribution; @@ -1428,6 +1492,7 @@  #include <cstdint>  #include <limits>  #include <algorithm> +#include <numeric>  #include <vector>  #include <string>  #include <istream> @@ -4075,7 +4140,7 @@  result_type s() const {return __p_.s();}    param_type param() const {return __p_;} - void param(const param_type& __p) {return __p_ = __p;} + void param(const param_type& __p) {__p_ = __p;}    result_type min() const {return 0;}  result_type max() const {return numeric_limits<result_type>::infinity();} @@ -5176,6 +5241,8 @@  return __is;  }   +// student_t_distribution +  template<class _RealType = double>  class student_t_distribution  { @@ -5220,7 +5287,7 @@  result_type n() const {return __p_.n();}    param_type param() const {return __p_;} - void param(const param_type& __p) {return __p_ = __p;} + void param(const param_type& __p) {__p_ = __p;}    result_type min() const {return -numeric_limits<result_type>::infinity();}  result_type max() const {return numeric_limits<result_type>::infinity();} @@ -5270,6 +5337,212 @@  return __is;  }   +// discrete_distribution + +template<class _IntType = int> +class discrete_distribution +{ +public: + // types + typedef _IntType result_type; + + class param_type + { + vector<double> __p_; + public: + typedef discrete_distribution distribution_type; + + param_type() {} + template<class _InputIterator> + param_type(_InputIterator __f, _InputIterator __l) + : __p_(__f, __l) {__init();} + param_type(initializer_list<double> __wl) + : __p_(__wl.begin(), __wl.end()) {__init();} + template<class _UnaryOperation> + param_type(size_t __nw, double __xmin, double __xmax, + _UnaryOperation __fw); + + vector<double> probabilities() const; + + friend bool operator==(const param_type& __x, const param_type& __y) + {return __x.__p_ == __y.__p_;} + friend bool operator!=(const param_type& __x, const param_type& __y) + {return !(__x == __y);} + + private: + void __init(); + + friend class discrete_distribution; + + template <class _CharT, class _Traits, class _IT> + friend + basic_ostream<_CharT, _Traits>& + operator<<(basic_ostream<_CharT, _Traits>& __os, + const discrete_distribution<_IT>& __x); +  + template <class _CharT, class _Traits, class _IT> + friend + basic_istream<_CharT, _Traits>& + operator>>(basic_istream<_CharT, _Traits>& __is, + discrete_distribution<_IT>& __x); + }; + +private: + param_type __p_; + +public: + // constructor and reset functions + discrete_distribution() {} + template<class _InputIterator> + discrete_distribution(_InputIterator __f, _InputIterator __l) + : __p_(__f, __l) {} + discrete_distribution(initializer_list<double> __wl) + : __p_(__wl) {} + template<class _UnaryOperation> + discrete_distribution(size_t __nw, double __xmin, double __xmax, + _UnaryOperation __fw) + : __p_(__nw, __xmin, __xmax, __fw) {} + explicit discrete_distribution(const param_type& __p) + : __p_(__p) {} + void reset() {} + + // generating functions + template<class _URNG> result_type operator()(_URNG& __g) + {return (*this)(__g, __p_);} + template<class _URNG> result_type operator()(_URNG& __g, const param_type& __p); + + // property functions + vector<double> probabilities() const {return __p_.probabilities();} + + param_type param() const {return __p_;} + void param(const param_type& __p) {__p_ = __p;} + + result_type min() const {return 0;} + result_type max() const {return __p_.__p_.size();} + + friend bool operator==(const discrete_distribution& __x, + const discrete_distribution& __y) + {return __x.__p_ == __y.__p_;} + friend bool operator!=(const discrete_distribution& __x, + const discrete_distribution& __y) + {return !(__x == __y);} + + template <class _CharT, class _Traits, class _IT> + friend + basic_ostream<_CharT, _Traits>& + operator<<(basic_ostream<_CharT, _Traits>& __os, + const discrete_distribution<_IT>& __x); +  + template <class _CharT, class _Traits, class _IT> + friend + basic_istream<_CharT, _Traits>& + operator>>(basic_istream<_CharT, _Traits>& __is, + discrete_distribution<_IT>& __x); +}; + +template<class _IntType> +template<class _UnaryOperation> +discrete_distribution<_IntType>::param_type::param_type(size_t __nw, + double __xmin, + double __xmax, + _UnaryOperation __fw) +{ + if (__nw > 1) + { + __p_.reserve(__nw - 1); + double __d = (__xmax - __xmin) / __nw; + double __d2 = __d / 2; + for (size_t __k = 0; __k < __nw; ++__k) + __p_.push_back(__fw(__xmin + __k * __d + __d2)); + __init(); + } +} + +template<class _IntType> +void +discrete_distribution<_IntType>::param_type::__init() +{ + if (!__p_.empty()) + { + if (__p_.size() > 1) + { + double __s = _STD::accumulate(__p_.begin(), __p_.end(), 0.0); + for (_STD::vector<double>::iterator __i = __p_.begin(), __e = __p_.end(); + __i < __e; ++__i) + *__i /= __s; + vector<double> __t(__p_.size() - 1); + _STD::partial_sum(__p_.begin(), __p_.end() - 1, __t.begin()); + swap(__p_, __t); + } + else + { + __p_.clear(); + __p_.shrink_to_fit(); + } + } +} + +template<class _IntType> +vector<double> +discrete_distribution<_IntType>::param_type::probabilities() const +{ + size_t __n = __p_.size(); + _STD::vector<double> __p(__n+1); + _STD::adjacent_difference(__p_.begin(), __p_.end(), __p.begin()); + if (__n > 0) + __p[__n] = 1 - __p_[__n-1]; + else + __p[0] = 1; + return __p; +} + +template<class _IntType> +template<class _URNG> +_IntType +discrete_distribution<_IntType>::operator()(_URNG& __g, const param_type& __p) +{ + uniform_real_distribution<double> __gen; + return static_cast<_IntType>( + _STD::upper_bound(__p.__p_.begin(), __p.__p_.end(), __gen(__g)) - + __p.__p_.begin()); +} + +template <class _CharT, class _Traits, class _IT> +basic_ostream<_CharT, _Traits>& +operator<<(basic_ostream<_CharT, _Traits>& __os, + const discrete_distribution<_IT>& __x) +{ + __save_flags<_CharT, _Traits> _(__os); + __os.flags(ios_base::dec | ios_base::left); + _CharT __sp = __os.widen(' '); + __os.fill(__sp); + size_t __n = __x.__p_.__p_.size(); + __os << __n; + for (size_t __i = 0; __i < __n; ++__i) + __os << __sp << __x.__p_.__p_[__i]; + return __os; +} + +template <class _CharT, class _Traits, class _IT> +basic_istream<_CharT, _Traits>& +operator>>(basic_istream<_CharT, _Traits>& __is, + discrete_distribution<_IT>& __x) +{ + typedef discrete_distribution<_IT> _Eng; + typedef typename _Eng::result_type result_type; + typedef typename _Eng::param_type param_type; + __save_flags<_CharT, _Traits> _(__is); + __is.flags(ios_base::dec | ios_base::skipws); + size_t __n; + __is >> __n; + std::vector<double> __p(__n); + for (size_t __i = 0; __i < __n; ++__i) + __is >> __p[__i]; + if (!__is.fail()) + swap(__x.__p_.__p_, __p); + return __is; +} +  _LIBCPP_END_NAMESPACE_STD    #endif // _LIBCPP_RANDOM